package de.uni_stuttgart.ipvs.ids.clocks.cristian;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import de.uni_stuttgart.ipvs.ids.clocks.Clock;
import de.uni_stuttgart.ipvs.ids.communicationLib.VSDatagramSocket;

/**
 * A Timeserver for the clock synchronization algorithm of Cristian. Send its
 * time to requesting clients for synchronization.
 * 
 * @author Team 3/4 Elkhan Dadashov, Ahmed Labib, Dhaval A Shah, Patrick Stortz
 */
public class Timeserver implements Runnable {

	/** The clock used by this Timeserver */
	private Clock clock;
	/** The VSDatagramSocket used for communication with the time clients */
	private VSDatagramSocket serverSocket;
	/** The maximum length of a reply of this Timeserver */
	protected final static int maxReplyLength = String.valueOf(Long.MIN_VALUE)
			.getBytes().length;

	/**
	 * Creates a new instance of a Timeserver
	 * 
	 * @param clock
	 *            The clock to be used by this Timeserver
	 * @param address
	 *            The address to be used by this Timeclient for communication
	 */
	public Timeserver(Clock clock, InetSocketAddress address) {
		this.clock = clock;
		serverSocket = new VSDatagramSocket(address);
	}

	@Override
	public void run() {

		String threadName = Thread.currentThread().getName();

		// system ready, reset the clock
		this.clock.setTime(0);
		System.out.println(threadName + " | Server running...");// DEBUG

		// loop and wait for requests of clients
		while (true) {
			// wait for a request
			byte[] requestData = new byte[Timeclient.syncMessage.length];
			DatagramPacket timeRequest = new DatagramPacket(requestData,
					requestData.length);
			serverSocket.receive(timeRequest);

			// create the reply with our current time
			DatagramPacket timeReply = null;
			try {
				byte[] replyData = String.valueOf(clock.getTime()).getBytes();
				timeReply = new DatagramPacket(replyData, replyData.length,
						timeRequest.getSocketAddress());
			} catch (IOException e) {
				System.err
						.println(threadName
								+ " | Could not create the reply for the client. Exception: "
								+ e.getMessage());// DEBUG
				// ignore this failed request and wait for the next one
				continue;
			}

			// send the request with current time
			try {
				serverSocket.send(timeReply);
			} catch (IOException e) {
				System.err
						.println(threadName
								+ " | Could not send the reply to the client. Exception: "
								+ e.getMessage());// DEBUG
				// ignore this failed request and wait for the next one
				continue;
			}

		}
	}

}
